﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
using System.Threading.Tasks;

namespace Pavilion.DesignerTool
{
    public class DrawingBoardXnaComponent : IXnaComponent
    {
        public DrawingBoardData DrawingBoardData;
        public IDrawTool DrawTool { get; set; }
        public bool IsCursorVisible { get; set; }

        private Vector2 CurrentFrameOrigin { get { return new Vector2(DrawingBoardData.FrameData.Frame.OriginX * DrawingBoardData.Scale, DrawingBoardData.FrameData.Frame.OriginY * DrawingBoardData.Scale); } }
        private Render render;

        public DrawingBoardXnaComponent()
        {
            render = new Render();
            DrawingBoardData = new DrawingBoardData();
        }

        public void Load(GraphicsDevice graphics, IServiceProvider services) { }
        public void Update(GameTime gametime) { }
        public void SizeChanged(double width, double height) { }

        public void Draw()
        {
            DrawBackgroundAnimations();
            DrawCurrentAnimation();

            if (DrawTool != null)
                DrawTool.DrawInterface(DrawingBoardData);
        }

        private void DrawBackgroundAnimations()
        {
            if (DrawingBoardData.AnimationSelectionInfo == null)
                return;

            IEnumerable<AnimationLayer> backgroundAnimation = DrawingBoardData.AnimationSelectionInfo.BackgroundAnimationCollection.Where(x => x.IsEnabled);

            foreach (AnimationLayer animationLayer in backgroundAnimation)
            {
                DrawBackgoundAnimationLayer(animationLayer, true);
                //int startingIndex = DetermineStartingIndex(animationLayer);
                //int endingIndex = DetermineEndingIndex(animationLayer);

                //for (int i = startingIndex; i <= endingIndex; i++)
                //{
                //    Frame frame = animationLayer.CurrentAnimationData.FrameDataCollection[i].Frame;
                //    Vector2 position = DeterminePositionOfIndex(animationLayer, i);
                //    frame.DrawOnScreen(position, new Color(255, 255, 255, 100), DrawingBoardData.Scale, default(Vector2), SpriteEffects.None);
                //}
            }
        }

        private void DrawBackgoundAnimationLayer(AnimationLayer animationLayer, bool drawCurrentFrameIndex)
        {
            int startingIndex = DetermineStartingIndex(animationLayer);
            int endingIndex = DetermineEndingIndex(animationLayer);

            for (int i = startingIndex; i <= endingIndex; i++)
            {
                if (drawCurrentFrameIndex || i != DrawingBoardData.AnimationSelectionInfo.CurrentFrameIndex)
                {
                    Frame frame = animationLayer.CurrentAnimationData.FrameDataCollection[i].Frame;
                    Vector2 position = DeterminePositionOfIndex(animationLayer, i);
                    frame.DrawOnScreen(position, new Color(255, 255, 255, 100), DrawingBoardData.Scale, default(Vector2), SpriteEffects.None);
                }
            }
        }

        private void DrawCurrentAnimation()
        {
            if (DrawingBoardData.FrameData == null)
                return;

            AnimationLayer animationLayer = DrawingBoardData.AnimationSelectionInfo.CurrentAnimationLayer;
            DrawBackgoundAnimationLayer(animationLayer, false);

            //int startingIndex = DetermineStartingIndex(DrawingBoardData.AnimationSelectionInfo.CurrentAnimationLayer);
            //int endingIndex = DetermineEndingIndex(DrawingBoardData.AnimationSelectionInfo.CurrentAnimationLayer);

            //for (int i = startingIndex; i <= endingIndex; i++)
            //{
            //    if (i != DrawingBoardData.AnimationSelectionInfo.CurrentFrameIndex)
            //    {
            //        Frame frame = DrawingBoardData.AnimationSelectionInfo.CurrentAnimationData.FrameDataCollection[i].Frame;
            //        Vector2 position = DeterminePositionOfIndex(DrawingBoardData.AnimationSelectionInfo.CurrentAnimationLayer, i);
            //        frame.DrawOnScreen(position, new Color(255, 255, 255, 100), DrawingBoardData.Scale, default(Vector2), SpriteEffects.None);
            //    }
            //}

            DrawingBoardData.FrameData.Frame.DrawOnScreen(animationLayer.PositionOnBoard, Color.White, DrawingBoardData.Scale, default(Vector2), SpriteEffects.None);
            DrawingBoardData.FrameData.Frame.DrawBoundingBoxOnScreen(animationLayer.PositionOnBoard, Color.Black, DrawingBoardData.Scale, default(Vector2), SpriteEffects.None);
        }

        public void BeginExecution()
        {
            if (DrawTool != null)
                DrawTool.BeginExecution(DrawingBoardData);
        }

        public void Execute()
        {
            if (DrawTool != null)
                DrawTool.Execute(DrawingBoardData);
        }

        public void EndExecution(Action creatUndoPointAction)
        {
            if (DrawTool != null)
                DrawTool.EndExecution(DrawingBoardData, creatUndoPointAction);
        }

        private Vector2 DeterminePositionOfIndex(AnimationLayer animationLayer, int frameIndex)
        {
            Vector2 framePositionOnBoard = animationLayer.PositionOnBoard;
            int currentIndex = DrawingBoardData.AnimationSelectionInfo.CurrentIndex - animationLayer.Offset;
            float xPos = framePositionOnBoard.X + (animationLayer.SpeedDistance * (frameIndex - currentIndex) * 10);

            return new Vector2(xPos, framePositionOnBoard.Y);
        }

        private int DetermineStartingIndex(AnimationLayer animationLayer)
        {
            int startingIndex = DrawingBoardData.AnimationSelectionInfo.CurrentIndex - animationLayer.Offset - DrawingBoardData.AnimationSelectionInfo.LeftIndexBounds;

            if (startingIndex > 0)
                return startingIndex;
            else
                return 0;
        }

        private int DetermineEndingIndex(AnimationLayer animationLayer)
        {
            int endingIndex = DrawingBoardData.AnimationSelectionInfo.CurrentIndex - animationLayer.Offset + DrawingBoardData.AnimationSelectionInfo.RightIndexBounds;
            int frameCount = (animationLayer.CurrentAnimationData == null) ? 0 : animationLayer.CurrentAnimationData.FrameDataCollection.Count;

            if (endingIndex < frameCount)
                return endingIndex;
            else
                return frameCount - 1;
        }
    }
}
